Skip to content

ADX-141: Refactor pipeline/pipelinestep CLI init commands to flag-based inputs#1010

Draft
Copilot wants to merge 6 commits intomasterfrom
copilot/adx-141-refactor-clarifai-pipeline
Draft

ADX-141: Refactor pipeline/pipelinestep CLI init commands to flag-based inputs#1010
Copilot wants to merge 6 commits intomasterfrom
copilot/adx-141-refactor-clarifai-pipeline

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

Interactive click.prompt() calls in pipeline init and pipelinestep init commands made them unusable in CI/CD and scripted environments. This replaces all interactive prompts with CLI flags, aligning with the model CLI interface. When flags are omitted, IDs are now resolved from the global config before falling back to an interactive prompt.

Why

  • Pipeline commands must work non-interactively in scripts, agents, and CI pipelines
  • Consistent CLI UX across all Clarifai commands (model CLI already uses flags)
  • user_id/app_id should be auto-detected from the active login context (~/.clarifai/config.yaml) rather than requiring explicit flags or producing unhelpful placeholder values

How

pipeline init — new flags replace all prompts:

# user_id/app_id auto-detected from global config (~/.clarifai/config.yaml)
clarifai pipeline init

# Fully explicit — fully scriptable
clarifai pipeline init \
  --user_id=my_user --app_id=my_app --pipeline_id=my-pipeline \
  --steps stepA --steps stepB

# Template init with parameter overrides (no prompts)
clarifai pipeline init --template=image-classification \
  --user_id=my_user --app_id=my_app \
  --set model_name=resnet50

pipelinestep init — new flags populate config directly:

clarifai pipelinestep init \
  --user_id=my_user --app_id=my_app --step_id=my-step

Key implementation details:

  • _init_interactive() renamed to _init_flag_based(); all click.prompt() calls removed from the scaffolding path
  • _init_from_template() now accepts user_id, app_id, pipeline_id, override_params as parameters; --set key=value replaces template parameter prompts
  • get_config_template() in pipeline_step_templates.py parameterized with step_id/user_id/app_id; TODO comments only generated when placeholder defaults are used
  • _DEFAULT_PIPELINE_ID constant extracted to avoid coupling between decorator default and runtime logic
  • Fixed Python scoping bug: list(steps) was calling the CLI list command (which shadows the built-in); changed to [*steps]
  • Added resolve_id() utility in clarifai/utils/cli.py: resolves a value from CLI flag → global config current context → interactive prompt. Used for user_id and app_id in both pipeline init and pipelinestep init
  • --num_steps now uses type=click.IntRange(min=1), rejecting 0 or negative values before any scaffold logic runs
  • All open(..., 'w') calls in pipelinestep init now include encoding='utf-8' to avoid platform-dependent encoding issues

Tests

  • All tests updated to use flag-based invocations instead of input= strings and click.prompt mocks
  • test_init_command_without_template_calls_interactive renamed to test_init_command_without_template_calls_flag_based
  • Pipeline step tests updated to always supply --user_id/--app_id flags (matching the new resolution behavior)
  • test_init_with_template_option and test_init_without_template_option updated to assert the full argument list passed to _init_from_template and _init_flag_based (prepared path, template name, user_id, app_id, pipeline_id, override_params/step_names)
  • 141 pipeline-related tests pass

Notes

  • If --user_id/--app_id are omitted and the global config has no values, the user is prompted interactively — making the command safe in both scripted and interactive shells
  • --num_steps N is available as a shorthand when step names don't matter (defaults to 2, minimum 1)
  • step_id in pipelinestep init remains optional; a # TODO: please fill in comment is generated in config.yaml when it is not provided

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

Copilot AI and others added 2 commits April 7, 2026 05:16
Copilot AI changed the title [WIP] Refactor clarifai pipeline to use flag-based inputs ADX-141: Refactor pipeline/pipelinestep CLI init commands to flag-based inputs Apr 7, 2026
Copilot AI requested a review from nitinbhojwani April 7, 2026 05:19
@nitinbhojwani nitinbhojwani requested a review from Copilot April 7, 2026 13:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Comment on lines +485 to +490
# Apply defaults for unset values
effective_user_id = user_id or "your_user_id"
effective_app_id = app_id or "your_app_id"
effective_pipeline_id = (
pipeline_id if pipeline_id and pipeline_id != _DEFAULT_PIPELINE_ID else template_name
)
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In template mode, effective_pipeline_id falls back to template_name whenever pipeline_id == _DEFAULT_PIPELINE_ID. Because the --pipeline_id option always supplies that default, this makes it impossible for a user to intentionally set a template-based pipeline’s ID to "hello-world-pipeline" (explicitly passing that value still gets replaced). Consider making --pipeline_id default to None and resolving defaults inside the template vs non-template branches so an explicitly provided value is always respected.

Copilot uses AI. Check for mistakes.
Comment on lines 306 to +375
@@ -309,17 +341,57 @@ def init(pipeline_path, template):
└── README.md # Documentation

PIPELINE_PATH: Path where to create the pipeline project structure. If not specified, the current directory is used by default.

Examples:

# Basic initialization with defaults
clarifai pipeline init

# Initialize with explicit IDs and steps
clarifai pipeline init --user_id=my_user --app_id=my_app --pipeline_id=my-pipeline --steps stepA --steps stepB

# Initialize with a specific number of steps
clarifai pipeline init --user_id=my_user --app_id=my_app --pipeline_id=my-pipeline --num_steps=3

# Initialize from a template
clarifai pipeline init --template=image-classification --user_id=my_user --app_id=my_app

# Initialize from a template with custom parameters
clarifai pipeline init --template=image-classification --user_id=my_user --app_id=my_app --set model_name=resnet50
"""
# Common setup logic
pipeline_path = _prepare_pipeline_path(pipeline_path, template)
if not pipeline_path:
return # Error already shown in _prepare_pipeline_path

# Resolve step names: explicit --steps take precedence, then generate from --num_steps
if steps:
resolved_steps = [*steps]
else:
default_names = ["stepA", "stepB", "stepC", "stepD", "stepE", "stepF"]
resolved_steps = [
default_names[i] if i < len(default_names) else f"step{i + 1}"
for i in range(num_steps)
]
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--num_steps currently accepts 0 or negative values, which produces an empty resolved_steps list and generates a pipeline project with no step directories/configs. Since the generated pipeline config’s step_directories and orchestration spec are meant to reference created step folders, this can lead to a non-functional scaffold. Consider enforcing a minimum of 1 (e.g., type=click.IntRange(min=1) or a runtime validation that errors when num_steps < 1).

Copilot uses AI. Check for mistakes.
Comment on lines 98 to 129
else:
pipeline_step_template = get_pipeline_step_template()
with open(pipeline_step_py_path, 'w') as f:
f.write(pipeline_step_template)
logger.info(f"Created {pipeline_step_py_path}")

# Create requirements.txt
requirements_path = os.path.join(pipeline_step_path, "requirements.txt")
if os.path.exists(requirements_path):
logger.warning(f"File {requirements_path} already exists, skipping...")
else:
requirements_template = get_requirements_template()
with open(requirements_path, 'w') as f:
f.write(requirements_template)
logger.info(f"Created {requirements_path}")

# Create config.yaml
config_path = os.path.join(pipeline_step_path, "config.yaml")
if os.path.exists(config_path):
logger.warning(f"File {config_path} already exists, skipping...")
else:
config_template = get_config_template()
# Pass explicit values; get_config_template uses placeholder defaults for None
config_template = get_config_template(
**{
k: v
for k, v in [('step_id', step_id), ('user_id', user_id), ('app_id', app_id)]
if v
}
)
with open(config_path, 'w') as f:
f.write(config_template)
logger.info(f"Created {config_path}")
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File writes in pipelinestep init use open(..., 'w') without an explicit encoding. Other CLI init flows in this repo write templates with encoding='utf-8' (e.g., clarifai/cli/pipeline.py:582). To avoid platform-dependent defaults and potential Unicode issues, write these files with an explicit UTF-8 encoding as well.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on:

this feedback

and

this feedback

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit a110b70:

  • All three open(..., 'w') calls in pipelinestep init now use encoding='utf-8'
  • --num_steps now uses type=click.IntRange(min=1), so 0 or negative values are rejected with a clear Click error message

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

Code Coverage

Package Line Rate Health
clarifai 45%
clarifai.cli 61%
clarifai.cli.templates 71%
clarifai.cli.templates.toolkits 100%
clarifai.client 65%
clarifai.client.auth 67%
clarifai.constants 100%
clarifai.datasets 100%
clarifai.datasets.export 69%
clarifai.datasets.upload 75%
clarifai.datasets.upload.loaders 37%
clarifai.models 100%
clarifai.rag 0%
clarifai.runners 52%
clarifai.runners.models 60%
clarifai.runners.pipeline_steps 39%
clarifai.runners.pipelines 72%
clarifai.runners.utils 62%
clarifai.runners.utils.data_types 72%
clarifai.schema 100%
clarifai.urls 58%
clarifai.utils 64%
clarifai.utils.evaluation 16%
clarifai.workflows 95%
Summary 60% (11908 / 19769)

Minimum allowed line rate is 50%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ADX-141 Refactor the clarifai pipeline, pipelinestep, and other pipeline commands to replace interactive prompts with flag-based inputs

3 participants